package org.ands.apps;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.ands.client.aad.ContentsRetrieverAAD;
import org.ands.client.abs.stat.ProcessAbsResponse;
import org.ands.client.ala.ContentsRetrieverALA;
import org.ands.client.ala.ContentsRetrieverALASpatial;
import org.ands.data.ContentsRetrieverCSV;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;


// TODO: Auto-generated Javadoc
/**
 * The Class Pen.
 *
 * @author      Melanie Adamson
 * @version     1.0
 * @since       2012-07-20
 */
public class Pen {
	
	
	
	/**
	 * Pen class main method.
	 * <p>
	 * This is the primary play-area for instigating
	 * interaction between various components.
	 * Various bits may be commented out temporarily when
	 * not in use.
	 * 
	 * Current play is as follows:
	 * Constructs XMLContentsRetriever in one of two (so far) ways, either:
	 * <ul><li>
	 * XMLContents that are constructed from a .csv file (whose name is
	 * provided as a program argument) of xpaths and associated values.
	 * The .csv first row contains 'xpath' in the first column and
	 * 'value' in the second column.  All subsequent rows have an actual
	 * xpath in the first column and an actual value for that xpath
	 * in the second column; or
	 * </li></ul>
	 * <ul><li>
	 * XML Contents are constructed from a public json feed of a particular
	 * URI (provided via program argument) where crosswalk files
	 * (two of whom have been specified via program arguments)
	 * is used to determine the mapping between xpaths and:
	 * default values; and json tree values.
	 * </ul></li>
	 * Passes XMLContents to the RIFCSWriter which writes the
	 * xpaths and values out to an xml file whose name is
	 * specified within program arguments.
	 *
	 * @param args the arguments
	 * @see org.ands.data.ContentsRetrieverCSV
	 * @see ands.org.rifcsconstructor.XMLContentsRetriever.mockXMLContents(String filename)
	 * @see org.ands.data.Contents
	 * @see ands.org.rifcsconstructor.RIFCSWriter
	 */
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		try{
			//testMini();
			//testRandom();
			//testRegex();
			//testAbsStat();
			//testGetLinks();
		}
		catch(Exception e){
			e.printStackTrace();
			assert(false);
		}
		
			
		if (args.length != 1){
			System.err.println("Requires path to config file");
			System.exit(0);
		}
		
		final String configFilename = args[0];
		if((configFilename == null) || (configFilename.isEmpty())){
			System.err.println("Requires valid config file");
			System.exit(0);
		}
		
		System.out.println("Reading values from "+configFilename);
		
		try {
			
			FileInputStream in = new FileInputStream(configFilename);
			
			Properties properties = new Properties();
			properties.load(in);
			in.close();
			
			ComponentManager componentManager = new ComponentManager();
			componentManager.generateRifCs(properties);
			
		} catch (Exception e) {
			System.err.println("Exception ["+e.getMessage()+"].");
			e.printStackTrace();
		}
	}
	
	/**
	 * Test random.
	 */
	public static void testRandom(){
		
		//String value = "EARTH | SCIENCE > BIOSPHERE > VEGETATION | NEWVALUE > CHLOROPHYLL > LAST";
		String value = "EARTH SCIENCE > BIOSPHERE > VEGETATION > CHLOROPHYLL | EARTH SCIENCE > BIOLOGICAL CLASSIFICATION > PLANTS | EARTH SCIENCE > OCEANS > OCEAN CHEMISTRY > PIGMENTS > CHLOROPHYLL | EARTH SCIENCE > BIOSPHERE > ECOLOGICAL DYNAMICS > ECOSYSTEM FUNCTIONS > PRIMARY PRODUCTION | CHLOROPHYLL | FLUOROMETER | LOCATION | SOUTHERN OCEAN | VOLUME | FLUOROMETERS | SHIPS | OCEAN > ARCTIC OCEAN | OCEAN > SOUTHERN OCEAN | GEOGRAPHIC REGION > POLAR";
		String xpath = "MockXpath";

			
		Map<String, Boolean> splitRuleMap = new HashMap<String, Boolean>() {{ 
	        put(" > ", false);
	        put(new String(" \\| "), false);
	    }};
		
	    List<String> splitValueList = new ArrayList<String>();		
		if((splitRuleMap != null) && (!splitRuleMap.isEmpty())){
			List<String> splitValueMasterList = new ArrayList<String>();
			splitValueMasterList.add(value);
			for(Map.Entry<String, Boolean> splitRule : splitRuleMap.entrySet()){
				splitValueList.clear();
				assert(splitValueList.isEmpty());
				splitValueList.addAll(splitValueMasterList);
				splitValueMasterList.clear();
				for(String splitValue : splitValueList){
					List<String> thisSplitList = testApplySplitRules(splitRule.getKey(), splitRule.getValue(), splitValue, xpath, 200);
					if(!thisSplitList.isEmpty()){
						System.out.println("\nAdding all:\n");
						for(String testSplit : thisSplitList){
							assert(!testSplit.isEmpty());
							System.out.println(testSplit);
						}
						splitValueMasterList.addAll(thisSplitList);
					}
				}
			}
			splitValueList = splitValueMasterList;
		}
		
		
	
		System.out.println("\n\nResults:\n");
		for(String testSplit : splitValueList){
			assert(!testSplit.isEmpty());
			System.out.println(testSplit);
		}
		
		System.exit(0);
	}
	
	/**
	 * Test apply split rules.
	 *
	 * @param splitSequence the split sequence
	 * @param retainSequence the retain sequence
	 * @param value the value
	 * @param xpath the xpath
	 * @param maxCharsRequired the max chars required
	 * @return the list
	 */
	private static List<String> testApplySplitRules(
			final String splitSequence,
			final boolean retainSequence,
			final String value,
			final String xpath,
			final int maxCharsRequired){
		
		if((splitSequence == null) || (splitSequence.isEmpty())){
			return Arrays.asList();
		}
		
		System.out.println("Split sequence "+splitSequence);
		System.out.println("Retain sequence "+retainSequence);
		System.out.println("Value "+value);
		if((value == null) || (value.isEmpty())){
			return Arrays.asList();
		}
		
		System.out.println("{Clean} Value ["+value+"] for child [" + xpath
				+ "] requires split at "+splitSequence+" - splitting value");
		
		List<String> splitValueList = new ArrayList<String>();
		
		// Find out whether we need to stuff back the sequence that we just split on - not appropriate
		// for a new line but useful if we have split on something like 'http:'
		List<String> splitValueRawList = Arrays.asList(value.split(splitSequence));
		
		// Only keep the non-empty values
		for(String splitValueRaw : splitValueRawList){
			if(!splitValueRaw.isEmpty()){
				splitValueList.add(splitValueRaw);
			}
		}
		
		// Check that we haven't exceeded size limit
		for(String splitValue: splitValueList){
			assert(!splitValue.isEmpty());
			assert(splitValue.length() <= maxCharsRequired);
		}
		
		if(!retainSequence){
			return splitValueList;
		}
			
		List<String> splitValuesRetain = new ArrayList<String>();
		
		for(int i=0; i < splitValueList.size(); ++i){
			String splitValue = splitValueList.get(i);
			if(i == 0){
				// For first value, only add back if it was there in the first place
				if(value.startsWith(splitSequence)){
					assert((splitSequence+splitValue).length() <= maxCharsRequired);
					splitValuesRetain.add(splitSequence+splitValue);
				}
				else{
					assert(splitValue.length() <= maxCharsRequired);
					splitValuesRetain.add(splitValue);
				}
				
			}
			else{
				// Strings other than the first
				assert((splitSequence+splitValue).length() <= maxCharsRequired);
				splitValuesRetain.add(splitSequence+splitValue);
			}
		}
		
		assert(splitValueList.size() == splitValuesRetain.size());
		
		return splitValuesRetain;
	}
	
	
	

	/**
	 * Test regex.
	 */
	public static void testRegex(){
		
		// http://www.vogella.com/articles/JavaRegularExpressions/article.html
		
//		String TEST1 = "Word and space and new line \n then more here";
//		String TEST2 = "Word and space";
//		String TEST3 = "Word\n";
//		String TEST4 = "Word";
//		String TEST5 = "\n";
//		String TEST6 = " ";
//		
//		// Test contains whitespace
//		System.out.println(TEST1.matches(".*\\s+.*")); // true
//		System.out.println(TEST2.matches(".*\\s+.*")); // true
//		System.out.println(TEST3.matches(".*\\s+.*")); // true
//		System.out.println(TEST4.matches(".*\\s+.*")); // false
//		System.out.println(TEST5.matches(".*\\s+.*")); // true
//		System.out.println(TEST6.matches(".*\\s+.*")); // true
//		
//		String[] splitArray = TEST1.split("\\s+");
//		for(String s : splitArray){
//			System.out.println(s);
//		}
//		
//		List<String> testValueList = new ArrayList<String>();
//		testValueList.add("word");						// ok
//		testValueList.add("word|word");					// ok
//		testValueList.add("word|word2");				// ok
//		testValueList.add("word|word2,word|word2");		// ok
//		testValueList.add("word4.,l;>|\n");				// notok
//		testValueList.add("word4.,l;>	");				// notok
//		testValueList.add(",|");						// notok
//		testValueList.add("\n");						// notok
//		testValueList.add(" ");							// notok
//		
//		for(String testValue: testValueList){
//			System.out.println((testValue.matches("[A-Za-z0-9|,]*") ? "ok\t" : "notok\t")+"["+testValue+"]");
//		}
		
		String test = new String("northlimit=%1$s; southlimit=%2$s; westlimit=%3$s; eastLimit=%4$s; projection=WGS84");
		//String test = new String("northlimit=%s; southlimit=%s; westlimit=%s; eastLimit=%s; projection=WGS84");
		List<String> valueList = Arrays.asList("1", "2", "3", "4");
		assert(valueList.size() == 4);
		System.out.println(String.format(test, valueList.toArray()));
		
		System.out.println("word %1$s\t\t" + "word %1$s".matches(".*%[0-9]*\\$*s+.*")); 				// true
		System.out.println("word %12$s\t\t" + "word %12$s".matches(".*%[0-9]*\\$*s+.*")); 			// true
		System.out.println("word %12$s word %1$s\t" + "word %12$s word %1s".matches(".*%\\$*s+.*")); 	// false
		System.out.println("word %s word %s\t\t" + "word %s word %s".matches(".*%\\$*s+.*")); 		// true
		
		System.out.println("word %12$s\t" + "word %12$s".matches(".*%[0-9]*\\$*s+.*")); 								// true
		System.out.println("word %1$s\t" + "word %1$s".matches(".*%[0-9]*\\$*s+.*")); 								// true
		System.out.println("word %s\t\t" + "word %s".matches(".*%[0-9]*\\$*s+.*")); 								// true
		System.out.println("word %s word %s\t\t" + "word %s word %s".matches(".*%[0-9]*\\$*s+.*")); 				// true
		System.out.println("word %s word %s word\t\t" + "word %s word %s word".matches(".*%[0-9]*\\$*s+.*")); 		// true
		
		System.out.println("\n");
		
		System.out.println("word %12$d\t" + "word %12$d".matches(".*%[0-9]*\\$*s+.*")); 								// false
		System.out.println("word %1$d\t" + "word %1$d".matches(".*%[0-9]*\\$*s+.*")); 								// false
		System.out.println("word %d\t\t" + "word %d".matches(".*%[0-9]*\\$*s+.*")); 								// false
		System.out.println("word %d word %d\t\t" + "word %d word %d".matches(".*%[0-9]*\\$*s+.*")); 				// false
		System.out.println("word %d word %d word\t\t" + "word %d word %d word".matches(".*%[0-9]*\\$*s+.*")); 		// false
		
		System.out.println("\n");
		
		System.out.println("word %12$s\t" + "word %12$s".matches(".*%[0-9]*\\$*s+.*")); 								// 
		System.out.println("word %1$s\t" + "word %1$s".matches(".*%[0-9]*\\$*s+.*")); 								// 
		System.out.println("word %s\t\t" + "word %s".matches(".*%[0-9]*\\$*s+.*")); 								// 
		System.out.println("word %s word %s\t\t" + "word %s word %s".matches(".*%[0-9]*\\$*s+.*")); 				// 
		System.out.println("word %s word %s word\t\t" + "word %s word %s word".matches(".*%[0-9]*\\$*s+.*")); 		// 
		
		System.out.println("\n");
		
		System.out.println("word %12$d\t" + "word %12$d".matches(".*%[0-9]*s+.*")); 								// 
		System.out.println("word %1$d\t" + "word %1$d".matches(".*%[0-9]*s+.*")); 								// 
		System.out.println("word %d\t\t" + "word %d".matches(".*%[0-9]*s+.*")); 								// 
		System.out.println("word %d word %d\t\t" + "word %d word %d".matches(".*%[0-9]*s+.*")); 				// 
		System.out.println("word %d word %d word\t\t" + "word %d word %d word".matches(".*%[0-9]*s+.*")); 		// 
		

		System.exit(0);
		
		
	}
	
	/**
	 * Test mini.
	 */
	public static void testMini(){
		
		String text = " The Quick Brown Fox Jumped Over\n The Lazy \t Dog\n";
		//System.out.println("["+text+"]");
		//String stripped = text.replace(".*\\s+.*", "");
		String stripped = text.replaceAll("\\s", "");
		System.out.println("["+stripped+"]");
		
		System.exit(0);
		
	}
	
	/**
	 * Test abs stat.
	 *
	 * @throws Exception the exception
	 */
	public static void testAbsStat() throws Exception{
		
		ProcessAbsResponse processAbsResponse = new ProcessAbsResponse();
		
		System.exit(0);
	}
	
	/**
	 * Test get links.
	 *
	 * @throws Exception the exception
	 */
	public static void testGetLinks() throws Exception{
		String uri = "http://webdav.data.aad.gov.au/metadata/iso-ands/";
		org.jsoup.nodes.Document doc = Jsoup.connect(uri).get();
		assert(doc != null);
		
		Elements links = doc.select("a[href]");
				
		System.out.println(links.size());
        for (org.jsoup.nodes.Element link : links) {
        	System.out.println(link.attr("abs:href"));
        }
        
        System.exit(0);
	}
	

}


